home *** CD-ROM | disk | FTP | other *** search
- /* Target-vector operations for controlling go32 processes, for GDB.
- Copyright 1994 Free Software Foundation, Inc.
- Contributed by DJ Delorie.
-
- This file is part of GDB.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include "defs.h"
- #include "frame.h" /* required by inferior.h */
- #include "inferior.h"
- #include "target.h"
- #include "wait.h"
- #include "gdbcore.h"
- #include "command.h"
- #include <signal.h>
-
- extern char **environ;
-
- /* Forward declaration */
- extern struct target_ops go32_ops;
-
- /* ╔════════════════════════════════════════════════════════════════════════════╗
- ║ Go32's external debugger interface routines ║
- ╚════════════════════════════════════════════════════════════════════════════╝ */
-
- #define SOME_PID 42
-
- int prog_has_started = 0;
-
- #include <sys/farptr.h>
- #define far
- #include <../go32/gotypes.h> /* from go32 sources */
- #include <../go32/tss.h>
- #include <../go32/extdebug.h>
- #include <../go32/paging.h>
-
- static ExternalDebuggerInfo edi;
- static TSS a_tss;
- static AREAS areas[MAX_AREA];
-
- static int my_ds;
- static int app_ds;
- static int edi_seg;
- static int edi_ofs;
-
- #define r_ofs(x) ((int)(&(((TSS *)0)->x)))
- static struct {
- int tss_ofs;
- int size;
- } regno_mapping[] = {
- r_ofs(tss_eax), 4,
- r_ofs(tss_ecx), 4,
- r_ofs(tss_edx), 4,
- r_ofs(tss_ebx), 4,
- r_ofs(tss_esp), 4,
- r_ofs(tss_ebp), 4,
- r_ofs(tss_esi), 4,
- r_ofs(tss_edi), 4,
- r_ofs(tss_eip), 4,
- r_ofs(tss_eflags), 4,
- r_ofs(tss_cs), 2,
- r_ofs(tss_ss), 2,
- r_ofs(tss_ds), 2,
- r_ofs(tss_es), 2,
- r_ofs(tss_fs), 2,
- r_ofs(tss_gs), 2
- };
-
- static struct {
- int go32_sig;
- int gdb_sig;
- } sig_map[] = {
- 0, TARGET_SIGNAL_BUS,
- 1, TARGET_SIGNAL_TRAP,
- 2, TARGET_SIGNAL_UNKNOWN,
- 3, TARGET_SIGNAL_TRAP,
- 4, TARGET_SIGNAL_FPE,
- 5, TARGET_SIGNAL_SEGV,
- 6, TARGET_SIGNAL_ILL,
- 7, TARGET_SIGNAL_FPE,
- 8, TARGET_SIGNAL_BUS,
- 9, TARGET_SIGNAL_FPE,
- 10, TARGET_SIGNAL_BUS,
- 11, TARGET_SIGNAL_SEGV,
- 12, TARGET_SIGNAL_SEGV,
- 13, TARGET_SIGNAL_SEGV,
- 14, TARGET_SIGNAL_SEGV,
- 16, TARGET_SIGNAL_FPE,
- 31, TARGET_SIGNAL_ILL,
- -1,-1
- };
-
- static void go32_edi_init()
- {
- int i;
- asm("movw $0xfe01,%ax");
- asm("int $0x21");
- asm("movl %edx,_edi_seg");
- asm("movl %eax,_edi_ofs");
- asm("xor %eax,%eax");
- asm("movw %ds,%ax");
- asm("movl %eax,_my_ds");
- movedata(edi_seg, edi_ofs, my_ds, (int)(&edi), sizeof(edi));
- movedata(edi.a_tss_seg, edi.a_tss_ofs, my_ds, (int)(&a_tss), sizeof(TSS));
- app_ds = a_tss.tss_ds;
- movedata(edi.areas_seg, edi.areas_ofs, my_ds, (int)areas, sizeof(areas));
- for (i=0; i<MAX_AREA; i++)
- {
- areas[i].first_addr -= edi.app_base;
- areas[i].last_addr -= edi.app_base;
- }
- }
-
- static void go32_edi_run_child(void)
- {
- int i;
- prog_has_started = 1;
-
- movedata(my_ds, (int)(&edi), edi_seg, edi_ofs, sizeof(edi));
- movedata(my_ds, (int)(&a_tss), edi.a_tss_seg, edi.a_tss_ofs, sizeof(TSS));
- asm("movw $0xfe00,%ax");
- asm("int $0x21");
- movedata(edi_seg, edi_ofs, my_ds, (int)(&edi), sizeof(edi));
- movedata(edi.a_tss_seg, edi.a_tss_ofs, my_ds, (int)(&a_tss), sizeof(TSS));
-
- movedata(edi.areas_seg, edi.areas_ofs, my_ds, (int)areas, sizeof(areas));
- for (i=0; i<MAX_AREA; i++)
- {
- areas[i].first_addr -= edi.app_base;
- areas[i].last_addr -= edi.app_base;
- }
- }
-
- static int invalid_addr(word32 a, unsigned len)
- {
- int i;
- if ((int)invalid_addr > 0)
- return 0;
- for (i=0; i<MAX_AREA; i++)
- if (a>=areas[i].first_addr && (a+len-1) <= areas[i].last_addr)
- return 0;
- return 1;
- }
-
- static int go32_edi_read_child(word32 child_addr, void *buf, unsigned len)
- {
- if (invalid_addr(child_addr, len))
- return 0;
- movedata(app_ds, child_addr, my_ds, (int)buf, len);
- return 0;
- }
-
- static int go32_edi_write_child(word32 child_addr, void *buf, unsigned len)
- {
- if (invalid_addr(child_addr, len))
- return 0;
- movedata(my_ds, (int)buf, app_ds, child_addr, len);
- return 0;
- }
-
- static char *new_argv[3] = {
- "gdb",
- 0,
- 0
- };
-
- void
- init_go32_extdebug(int *argc, char ***argv)
- {
- char *fn;
- int i, v;
- int tenvp;
-
- go32_edi_init();
-
- fn = (char *)malloc(edi.filename_len + 1);
- movedata(edi.filename_seg, edi.filename_ofs, my_ds, (int)(fn), edi.filename_len+1);
-
- #if 0
- printf("filename: %s\n", fn);
-
- printf("text: %#08x - %#08x\n", areas[A_text].first_addr, areas[A_text].last_addr);
- printf("data: %#08x - %#08x\n", areas[A_data].first_addr, areas[A_data].last_addr);
- printf("bss: %#08x - %#08x\n", areas[A_bss].first_addr, areas[A_bss].last_addr);
-
- printf("stack: %#x\n", a_tss.tss_esp);
- #endif
-
- go32_edi_read_child(a_tss.tss_esp+8, &tenvp, 4);
-
- new_argv[1] = fn;
-
- for (i=0; ; i++)
- {
- int ep;
- char *s;
- go32_edi_read_child(tenvp+i*4, &ep, 4);
- if (!ep)
- break;
- }
- environ = (char **)malloc((i+1) * sizeof(char *));
-
- for (i=0; ; i++)
- {
- int ep;
- char *s;
- go32_edi_read_child(tenvp+i*4, &ep, 4);
- if (!ep)
- {
- environ[i] = 0;
- break;
- }
- _farsetsel(app_ds);
- for (v=0; _farnspeekb(ep+v); v++);
- environ[i] = (char *)malloc(v+1);
- go32_edi_read_child(ep, environ[i], v+1);
- }
-
- *argc = 2;
- *argv = new_argv;
- }
-
- /* ───────────────────────────────────────────────────────────────────────────── */
-
- /* special sbrk that uses local heap and zeros memory. */
- void *
- sbrk(int l)
- {
- extern int end;
- static int sold = (int)&end;
- memset(sold, 0, l);
- sold += l;
- return (void *)(sold-l);
- }
-
- /* ═════════════════════════════════════════════════════════════════════════════ */
-
- static void
- go32_open(char *name, int from_tty)
- {
- printf("Use the `run' command to run go32 programs\n");
- }
-
- /* ───────────────────────────────────────────────────────────────────────────── */
-
- static void go32_close(int quitting)
- {
- }
-
- /* ───────────────────────────────────────────────────────────────────────────── */
-
- static void
- go32_attach(char *args, int from_tty)
- {
- printf("Use the `run' command to run go32 programs\n");
- }
-
- /* ───────────────────────────────────────────────────────────────────────────── */
-
- static void
- go32_detach(char *args, int from_tty)
- {
- }
-
- /* ───────────────────────────────────────────────────────────────────────────── */
-
- static int resume_is_step;
-
- static void
- go32_resume(int pid, int step, enum target_signal siggnal)
- {
- resume_is_step = step;
- }
-
- /* ───────────────────────────────────────────────────────────────────────────── */
-
- static int
- go32_wait(int pid, struct target_waitstatus *status)
- {
- /* printf("go32_wait %d\n", pid); */
- if (resume_is_step)
- a_tss.tss_eflags |= 0x0100;
- else
- a_tss.tss_eflags &= 0xfeff;
- go32_edi_run_child();
- if (a_tss.tss_irqn == 0x21)
- {
- status->kind = TARGET_WAITKIND_EXITED;
- status->value.integer = a_tss.tss_eax & 0xff;
- }
- else
- {
- int i;
- status->value.sig = TARGET_SIGNAL_UNKNOWN;
- for (i=0; sig_map[i].go32_sig != -1; i++)
- if (a_tss.tss_irqn == sig_map[i].go32_sig)
- {
- status->value.sig = sig_map[i].gdb_sig;
- break;
- }
- status->kind = TARGET_WAITKIND_STOPPED;
- }
- return SOME_PID;
- }
-
- /* ───────────────────────────────────────────────────────────────────────────── */
-
- static void
- go32_fetch_registers(int regno)
- {
- if (regno >= 0)
- supply_register(regno, (char *)&a_tss + regno_mapping[regno].tss_ofs);
- else
- {
- int r;
- for (r=0; r<sizeof(regno_mapping)/sizeof(regno_mapping[0]); r++)
- supply_register(r, (char *)&a_tss + regno_mapping[r].tss_ofs);
- }
- }
-
- /* ───────────────────────────────────────────────────────────────────────────── */
-
- static void store_register(int regno)
- {
- char *rp = (char *)&a_tss + regno_mapping[regno].tss_ofs;
- int v = *(int *)(®isters[REGISTER_BYTE(regno)]);
- switch (regno_mapping[regno].size)
- {
- case 4:
- *(int *)rp = v;
- break;
- case 2:
- *(short *)rp = v;
- break;
- }
- }
-
- static void
- go32_store_registers(int regno)
- {
- if (regno >= 0)
- store_register(regno);
- else
- {
- int r;
- for (r=0; r<sizeof(regno_mapping)/sizeof(regno_mapping[0]); r++)
- store_register(regno);
- }
- }
-
- /* ───────────────────────────────────────────────────────────────────────────── */
-
- static void
- go32_prepare_to_store(void)
- {
- }
-
- /* ───────────────────────────────────────────────────────────────────────────── */
-
- static int
- go32_xfer_memory(CORE_ADDR memaddr, char *myaddr, int len, int write,
- struct target_ops *target)
- {
- /* printf("go32_xfer_memory %x %x %d %d\n", memaddr, myaddr, len, write); */
- if (write)
- go32_edi_write_child(memaddr, myaddr, len);
- else
- go32_edi_read_child(memaddr, myaddr, len);
- return len;
- }
-
- /* ───────────────────────────────────────────────────────────────────────────── */
-
- static void
- go32_files_info(struct target_ops *target)
- {
- printf_filtered("You are running a go32 program called `%s'\n", new_argv[1]);
- }
-
- /* ───────────────────────────────────────────────────────────────────────────── */
-
- static void
- go32_kill_inferior(void)
- {
- /* nothing to do */
- }
-
- /* ───────────────────────────────────────────────────────────────────────────── */
-
- static void
- go32_create_inferior(char *exec_file, char *args, char **env)
- {
- if (prog_has_started)
- {
- printf("The program has been started once already. Please quit and restart gdb.\n");
- return;
- }
- inferior_pid = SOME_PID;
- push_target(&go32_ops);
- clear_proceed_status();
- proceed((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
- }
-
- /* ───────────────────────────────────────────────────────────────────────────── */
-
- static void
- go32_mourn_inferior(void)
- {
- unpush_target(&go32_ops);
- }
-
- /* ───────────────────────────────────────────────────────────────────────────── */
-
- static int go32_can_run(void)
- {
- return 1;
- }
-
- /* ───────────────────────────────────────────────────────────────────────────── */
-
- static void ignore(void) {}
- static void ignore2(char *a,int b) {}
-
- /* ═════════════════════════════════════════════════════════════════════════════ */
-
- struct target_ops go32_ops = {
- "go32", /* to_shortname */
- "go32 target process", /* to_longname */
- "Program loaded by go32, when gdb is used as an external debugger", /* to_doc */
- go32_open, /* to_open */
- go32_close, /* to_close */
- go32_attach, /* to_attach */
- go32_detach, /* to_detach */
- go32_resume, /* to_resume */
- go32_wait, /* to_wait */
- go32_fetch_registers, /* to_fetch_registers */
- go32_store_registers, /* to_store_registers */
- go32_prepare_to_store, /* to_prepare_to_store */
- go32_xfer_memory, /* to_xfer_memory */
- go32_files_info, /* to_files_info */
- memory_insert_breakpoint, /* to_insert_breakpoint */
- memory_remove_breakpoint, /* to_remove_breakpoint */
- ignore, /* to_terminal_init */
- ignore, /* to_terminal_inferior */
- ignore, /* to_terminal_ours_for_output */
- ignore, /* to_terminal_ours */
- ignore2, /* to_terminal_info */
- go32_kill_inferior, /* to_kill */
- 0, /* to_load */
- 0, /* to_lookup_symbol */
- go32_create_inferior, /* to_create_inferior */
- go32_mourn_inferior, /* to_mourn_inferior */
- go32_can_run, /* to_can_run */
- 0, /* to_notice_signals */
- process_stratum, /* to_stratum */
- 0, /* to_next */
- 1, /* to_has_all_memory */
- 1, /* to_has_memory */
- 1, /* to_has_stack */
- 1, /* to_has_registers */
- 1, /* to_has_execution */
- 0, /* sections */
- 0, /* sections_end */
- OPS_MAGIC /* to_magic */
- };
-
- void
- _initialize_inftarg ()
- {
- add_target (&go32_ops);
- }
-